/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the Graphics Dojo project on Qt Labs.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 or 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************
**
** Divided and edited for use in a Bachelor Project
** by Oskar Kvamme and Endre Notland
** The code has been republished under similar license
**
****************************************************************************/


#include "LightMaps.h"
#include "mapmethods.h"

LightMaps::LightMaps(QWidget *parent)
            : QWidget(parent)
            , pressed(false)
            , snapped(false)
            , trackMap(true)
            , waypointMode(false) {
        m_normalMap = new SlippyMap(this);
        m_largeMap = new SlippyMap(this);
        connect(m_normalMap, SIGNAL(updated(QRect)), SLOT(updateMap(QRect)));
        connect(m_largeMap, SIGNAL(updated(QRect)), SLOT(update()));

        QNetworkDiskCache *cache = new QNetworkDiskCache;
        cache->setCacheDirectory(QDesktopServices::storageLocation
                                 (QDesktopServices::CacheLocation));
        m_manager.setCache(cache);
        connect(&m_manager, SIGNAL(finished(QNetworkReply*)),
                this, SLOT(handleNetworkData(QNetworkReply*)));

        getWaypointsFromServer();

        timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(getWaypointsFromServer()));
        timer->start(120000);
}

void LightMaps::setCenter(qreal lat, qreal lng) {
    m_normalMap->latitude = lat;
    m_normalMap->longitude = lng;
    m_largeMap->longitude = lng;
    m_largeMap->latitude = lat;
    m_normalMap->invalidate();
    m_largeMap->invalidate();
}

bool LightMaps::getTrackMap(){
    return trackMap;
}

void LightMaps::updateMap(const QRect &r) {
        update(r);
}

void LightMaps::toggleTrackMap(){
    trackMap = !trackMap;
}

void LightMaps::waypointSlot(){
    waypointMode = !waypointMode;
    if (waypointMode){
        trackMap = false;
        emit updateTrackButton();
        QInputDialog di;
        di.setTextValue("Waypoint text here");
        di.setLabelText("Enter Waypoint text");
        di.exec();
        points.append(Waypoint(di.textValue()));
    }else{
        sendPoint(points.back());
    }
}

void LightMaps::sendPoint(const Waypoint& w){
    QHttpRequestHeader header("POST", "/qtserver/index.php/api/setmarker");
    header.setValue("Host", "okvamme.com");

    QHttp *http = new QHttp(this);
    http->setHost("okvamme.com");
    header.setValue( "User-Agent", "Qt Map Application");
    header.setContentType("application/x-www-form-urlencoded");
    QString searchString = "lat=" + QString::number(double(w.getLatitude())) + "&lon=" + QString::number(double(w.getLongitude())) + "&desc=" + w.getText();
    http->request(header,searchString.toUtf8());
}

void LightMaps::getWaypointsFromServer(){
    QNetworkRequest request;
    request.setUrl(QUrl("http://okvamme.com/qtserver/index.php/api/getmarkersxml"));
    request.setRawHeader("User-Agent", "Qt Map Application");
    m_manager.get(request);
}

void LightMaps::handleNetworkData(QNetworkReply *reply) {
      WaypointParser handler;

      QXmlInputSource source(reply);

      QXmlSimpleReader reader;
      reader.setContentHandler(&handler);

      reader.parse(source);
      addToList(handler.list);
}


void LightMaps::addToList(const QLinkedList<Waypoint> &list){
    points.clear();
    foreach (Waypoint w, list){
        points.append(w);
    }
}

void LightMaps::resizeEvent(QResizeEvent *) {
    m_normalMap->width = width();
    m_normalMap->height = height();
    m_normalMap->invalidate();
    m_largeMap->width = m_normalMap->width * 2;
    m_largeMap->height = m_normalMap->height * 2;
    m_largeMap->invalidate();
}

void LightMaps::drawWaypoints(QPainter *p){
    foreach (Waypoint w, points){
        w.calcPos(m_normalMap->latitude, m_normalMap->longitude, m_normalMap->zoom, tdim, height(), width());
        p->drawEllipse(w.getDrawPoint(), 10, 10);
        //p->drawPixmap(w.getDrawPoint(), QPixmap("http://www.openstreetmap.org/openlayers/img/marker.png"));
        p->drawText(w.getDrawPoint(), w.getText());
    }
}

void LightMaps::paintEvent(QPaintEvent *event) {
    QPainter p;
    p.begin(this);
    m_normalMap->render(&p, event->rect());
    p.setPen(Qt::black);
    p.setBrush(Qt::green);

    if (trackMap){
        p.drawEllipse(QPoint(width()/2,height()/2), 10, 10);
        p.drawText(QPoint(width()/2,height()/2), "Center");
    }

    if (waypointMode && pressed){
        QPointF pressP(pressPos.x(), pressPos.y());
        QPointF center(width()/2, height()/2);
        QPointF delta = center - pressP;
        QPointF dx = delta / qreal(tdim);
        QPointF cent = MapMethods::tileForCoordinate(m_normalMap->latitude, m_normalMap->longitude, m_normalMap->zoom);
        QPointF wayP = cent - dx;

        points.back().setPosition(wayP.y(), wayP.x(), m_normalMap->zoom);
    }

    p.setBrush(Qt::red);
    drawWaypoints(&p);
    p.setPen(Qt::black);
    p.drawText(rect(),  Qt::AlignBottom | Qt::TextWordWrap, "Map data CCBYSA 2009 OpenStreetMap.org contributors");
    p.end();
}



void LightMaps::mousePressEvent(QMouseEvent *event) {
    if (event->buttons() != Qt::LeftButton)
        return;
    pressed = snapped = true;
    pressPos = dragPos = event->pos();
}

void LightMaps::mouseMoveEvent(QMouseEvent *event) {
    if (!event->buttons()){
        return;
    }

    if (!pressed || !snapped) {
        QPoint delta = event->pos() - pressPos;
        pressPos = event->pos();
        m_normalMap->pan(delta);
        return;
    } else {
        const int threshold = 10;
        QPoint delta = event->pos() - pressPos;
        if (snapped) {
            snapped &= delta.x() < threshold;
            snapped &= delta.y() < threshold;
            snapped &= delta.x() > -threshold;
            snapped &= delta.y() > -threshold;
        }
    }
}

void LightMaps::mouseReleaseEvent(QMouseEvent *) {
    update();
}

void LightMaps::keyPressEvent(QKeyEvent *event) {
    if (event->key() == Qt::Key_Left)
        m_normalMap->pan(QPoint(20, 0));
    if (event->key() == Qt::Key_Right)
        m_normalMap->pan(QPoint(-20, 0));
    if (event->key() == Qt::Key_Up)
        m_normalMap->pan(QPoint(0, 20));
    if (event->key() == Qt::Key_Down)
        m_normalMap->pan(QPoint(0, -20));
    if (event->key() == Qt::Key_F7){
        m_normalMap->zoom++;
        m_largeMap->zoom++;
        pressed = false;
        dragPos = QPoint(width() / 2, height() / 2);
        resizeEvent(NULL);
    }
    if (event->key() == Qt::Key_F8){
        m_normalMap->zoom--;
        m_largeMap->zoom--;
        pressed = false;
        dragPos = QPoint(width() / 2, height() / 2);
        resizeEvent(NULL);
    }
}
